package com.amat0urheu.utils;


import com.amat0urheu.dao.IpPortMapper;
import com.amat0urheu.pojo.CloudPojo.*;
import org.openstack4j.api.Builders;
import org.openstack4j.api.OSClient;
import org.openstack4j.api.compute.ServerService;
import org.openstack4j.model.common.ActionResponse;
import org.openstack4j.model.common.Identifier;
import org.openstack4j.model.compute.Flavor;
import org.openstack4j.model.compute.*;
import org.openstack4j.model.compute.actions.RebuildOptions;
import org.openstack4j.model.compute.builder.ServerCreateBuilder;
import org.openstack4j.model.network.IPVersionType;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.Subnet;
import org.openstack4j.openstack.OSFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class CloudUtils {

    private static  IpPortMapper ipPortMapper;
    @Autowired
    public CloudUtils(IpPortMapper ipPortMapper){
        CloudUtils.ipPortMapper = ipPortMapper;
    }
    //获取openstack客户端
    public static OSClient.OSClientV3 getOsclient(OpenStack openStack) {
        OSClient.OSClientV3 osClient = OSFactory.builderV3()
                .endpoint(openStack.getAuthUrl())
                .credentials(openStack.getUsername(), openStack.getPassword(), Identifier.byName(openStack.getUserDomainName()))
                .scopeToProject(Identifier.byId(openStack.getProjectid()), Identifier.byName(openStack.getProjectDomainName()))
                .authenticate();
        return osClient;
    }
/*    public static void testStudy() {
        String identity = "admin";
        String credential = "123123";
        String endpoint = "http://192.168.201.17:5000/v3";

        NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova")
                .endpoint(endpoint)
                .credentials(identity, credential)
                .buildApi(NovaApi.class);

        ServerApi serverApi = novaApi.getServerApi("your-project-id");

        FluentIterable<org.jclouds.openstack.nova.v2_0.domain.Server> servers = serverApi.listInDetail().concat();

        for (org.jclouds.openstack.nova.v2_0.domain.Server server : servers) {
            System.out.println(server.getName() + " - " + server.getId());
        }

    }*/

    public static List<VMservice> getVMservices(List<OpenStack> openstacks) {
        List<VMservice> vmList = new ArrayList<>();
        //获得现在这几个服务器中存在的实例
        for (OpenStack openstack:openstacks) {
            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            ServerService serverService = osClient.compute().servers();
            List<? extends Server> servers = serverService.list();
            for (Server server : servers) {
                if(server.getVmState().equalsIgnoreCase("building")){
                    System.err.println("ID: "+server.getId()+"  此服务器正在初始化");
                }else {
                    if(server.getName().contains("实验")){
                        VMservice vm = new VMservice();
                        vm.setVmID(server.getId());
                        vm.setStatus(String.valueOf(server.getStatus()));
                        VNCConsole vncConsole = serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
                        serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
                        String noVNCUrl = vncConsole.getURL();
                        List<IpPort> ipPorts = ipPortMapper.getIpPorts();
                        for (IpPort ipPort :ipPorts) {
                            if(noVNCUrl.contains(ipPort.getPreIpport())){
                                noVNCUrl=noVNCUrl.replace(ipPort.getPreIpport(),ipPort.getAftIpport());
                            }
                        }
                        vm.setNoVNC(noVNCUrl);
                        vmList.add(vm);
                    }
                    else {
                        VMservice raceVm = new VMservice();
                        raceVm.setVmID(server.getId());
                        raceVm.setStatus(String.valueOf(server.getStatus()));
                        VNCConsole vncConsole = serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
                        serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
                        String noVNCUrl = vncConsole.getURL();
                        List<IpPort> ipPorts = ipPortMapper.getIpPorts();
                        for (IpPort ipPort :ipPorts) {
                            if(noVNCUrl.contains(ipPort.getPreIpport())){
                                noVNCUrl=noVNCUrl.replace(ipPort.getPreIpport(),ipPort.getAftIpport());
                            }
                        }
                        raceVm.setNoVNC(noVNCUrl);
                        vmList.add(raceVm);
                        System.out.println(raceVm);
                    }


                }
            }
        }
        return vmList;
    }

    public static String getVMIP(Server server){
        for (List<? extends Address> addresses : server.getAddresses().getAddresses().values()) {
            for (Address address : addresses) {
                if (address.getVersion() == 4) {
                    return address.getAddr();
                }
            }
        }
        return "无IP地址";
    }

    public static VMservice createVMservices(String name, OpenStack openstack, String vmName, Integer num, String networkName, String flavorName) {
        System.out.println("进入镜像创建方法,正在创建"+vmName);
            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            String instanceName = name+"-"+vmName+"-"+num;
            Image image = null;

        for (Image a: osClient.compute().images().list()) {
            if(a.getName().equals(vmName)){
                image=a;
                }
        }
            // 获取网络
            Network network = osClient.networking().network().list().stream()
                    .filter(n -> n.getName().equals(networkName))
                    .findFirst()
                    .orElse(null);

            // 获取硬件规格
            Flavor flavor = osClient.compute().flavors().list().stream()
                    .filter(f -> f.getName().equalsIgnoreCase(flavorName))
                    .findFirst()
                    .orElse(null);
//            flavor.getId()

            List<String> ls=new ArrayList<>();
            ls.add(network.getId());

        ServerCreateBuilder serverCreateBuilder = osClient.compute().servers().serverBuilder()
                .name(instanceName)
                .flavor(flavor)
                .image(image)
                .networks(ls)
                .keypairName("testkey");

        Server server = osClient.compute().servers().bootAndWaitActive(serverCreateBuilder.build(),600000);


        VMservice experimentVm = new VMservice(server.getId(),num,name,instanceName,new Date(),new Date(),"BUILDING");
        ServerService serverService = osClient.compute().servers();
        experimentVm.setVmID(server.getId());
        experimentVm.setStatus(String.valueOf(server.getStatus()));
        VNCConsole vncConsole = serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        String noVNCUrl = vncConsole.getURL();
        List<IpPort> ipPorts = ipPortMapper.getIpPorts();
        for (IpPort ipPort :ipPorts) {
            if(noVNCUrl.contains(ipPort.getPreIpport())){
                noVNCUrl=noVNCUrl.replace(ipPort.getPreIpport(),ipPort.getAftIpport());
            }
        }
        experimentVm.setNoVNC(noVNCUrl);
        System.err.println(experimentVm);
        return experimentVm;
    }
    public static RaceVm createRaceVms(String name, OpenStack openstack, String vmName, Integer num, String networkName, String flavorName,List<String> flags) {

        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        String instanceName = name+"-"+vmName+"-"+num;
        Image image = null;

        for (Image a: osClient.compute().images().list()) {
            if(a.getName().equals(vmName)){
                image=a;
            }
        }
        // 获取网络
        Network network = osClient.networking().network().list().stream()
                .filter(n -> n.getName().equals(networkName))
                .findFirst()
                .orElse(null);

        // 获取硬件规格
        Flavor flavor = osClient.compute().flavors().list().stream()
                .filter(f -> f.getName().equalsIgnoreCase(flavorName))
                .findFirst()
                .orElse(null);

        List<String> ls=new ArrayList<>();
        ls.add(network.getId());


        Map<String, String> metadata = new HashMap<>();
        metadata.put("range","true");
        for (int i =0;i<flags.size();i++){
            metadata.put("flag"+(i+1),flags.get(i));
        }
        ServerCreateBuilder serverCreateBuilder = osClient.compute().servers().serverBuilder()
                .name(instanceName)
                .flavor(flavor)
                .image(image)
                .networks(ls)
                .keypairName("testkey").addMetadata(metadata);


        Server server = osClient.compute().servers().bootAndWaitActive(serverCreateBuilder.build(),600000);
        ServerService serverService = osClient.compute().servers();

        RaceVm raceVm = new RaceVm(server.getId(),num,name,instanceName,new Date(),new Date(),"BUILDING");
        raceVm.setVmID(server.getId());
        raceVm.setStatus(String.valueOf(server.getStatus()));
        VNCConsole vncConsole = serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        String noVNCUrl = vncConsole.getURL();
        List<IpPort> ipPorts = ipPortMapper.getIpPorts();
        for (IpPort ipPort :ipPorts) {
            if(noVNCUrl.contains(ipPort.getPreIpport())){
                noVNCUrl=noVNCUrl.replace(ipPort.getPreIpport(),ipPort.getAftIpport());
            }
        }
        raceVm.setNoVNC(noVNCUrl);
        System.err.println(raceVm);
        return raceVm;
    }


    public static List<com.amat0urheu.pojo.CloudPojo.Flavor> getflavors (OpenStack openstack) {

        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        List<? extends Flavor> flavors = osClient.compute().flavors().list();
        List< com.amat0urheu.pojo.CloudPojo.Flavor> flavorslist = new ArrayList<>();
        for (int i=0;i<flavors.size();i++){
            com.amat0urheu.pojo.CloudPojo.Flavor flavor= new com.amat0urheu.pojo.CloudPojo.Flavor(flavors.get(i).getId(),flavors.get(i).getName(),flavors.get(i).getVcpus(),  flavors.get(i).getRam(),flavors.get(i).getDisk(),openstack.getOpenstackIP());
            flavorslist.add(flavor);
        }
        return flavorslist;
    }

    public static String createflavor (com.amat0urheu.pojo.CloudPojo.Flavor flavor2, OpenStack openstack) {

        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        Flavor flavor = Builders.flavor()
                .name(flavor2.getName())
                .vcpus(flavor2.getVcpus())
                .ram(flavor2.getRam())
                .disk(flavor2.getDis())
                .build();
        flavor = osClient.compute().flavors().create(flavor);
        // 调用API创建实例类型
        System.out.println(flavor);
        return flavor.getId();
    }

    public static List<VMservice> removeflavor (OpenStack openstack,String flavorName) {

        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        List<? extends Flavor> flavors = osClient.compute().flavors().list();
        for (Flavor flavor : flavors) {
            if (flavor.getName().equals(flavorName)) {
                // 找到了需要删除的实例类型
                // 删除实例类型的操作
                osClient.compute().flavors().delete(flavor.getId());
                break;
            }
        }
        return null;
    }










    public static List<VMservice> operateVm(String vmID,OpenStack openstack,String action) {
            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            // 获取服务器服务
            ServerService serverService = osClient.compute().servers();
            ActionResponse response = null;
            if(action.equals("suspend")){
                response = serverService.action(vmID, Action.SUSPEND);

            }
            else if(action.equals("resume")){
                response = serverService.action(vmID, Action.RESUME);

            }else if(action.equals("stop")){
                response = serverService.action(vmID, Action.STOP);
            }
            else if(action.equals("start")){
                response = serverService.action(vmID, Action.START);

            }
            // 检查操作是否成功
            if (response.isSuccess()) {
                System.out.println("实例"+action+"成功");
            } else {
                System.out.println("实例"+action+"失败：" + response.getFault());
            }

        return null;
    }













    public static List< NetWork> getNetWorks(OpenStack openstack) {


        List<NetWork> networks = new ArrayList<>();
        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        for (Network AnetWork : osClient.networking().network().list()) {
            NetWork network = new NetWork();
            network.setName(AnetWork.getName());
            network.setNetWorkId(AnetWork.getId());
            network.setNetWorksubnet(AnetWork.getNeutronSubnets().get(0).getCidr());
            network.setGateWayIP(AnetWork.getNeutronSubnets().get(0).getGateway());
            network.setStatus(String.valueOf(AnetWork.getStatus()));
            network.setOpenstackIP(openstack.getOpenstackIP());
            networks.add(network);
        }
        return networks;
    }
    public static  NetWork CreateNetWork(List<OpenStack> openstacks,NetWork netWork) {

        for (OpenStack openstack : openstacks) {
            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            Network network1 = osClient.networking().network()
                    .create(Builders.network()
                            .name(netWork.getName())
                            .adminStateUp(true) // Network state is up
                            .build());

            Subnet subnet = osClient.networking().subnet()
                    .create(Builders.subnet()
                            .name(netWork.getName())
                            .networkId(network1.getId()) // Associate the subnet with the created network
                            .ipVersion(IPVersionType.V4) // IPv4 subnet
                            .cidr(netWork.getNetWorksubnet()) // CIDR notation for the subnet range
                            .gateway(netWork.getGateWayIP())
                            .enableDHCP(true) // Enable DHCP for the subnet
                            .build());
            netWork.setNetWorkId(network1.getId());
            netWork.setStatus("ACTIVE");

        }


        return  netWork;
    }
    public static boolean DleteNetWork(List<OpenStack> openstacks,String netWorkId) {

        boolean a=false;
        for (OpenStack openstack : openstacks) {
            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            ActionResponse actionResponse= osClient.networking().network().delete(netWorkId);
            a=actionResponse.isSuccess();
        }


        return  a;
    }
    public static  List<ImagePojo> getImages(OpenStack openstack) {

            OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
            List<ImagePojo> imagesList=new ArrayList();
            List<  ? extends Image>  images= osClient.compute().images().list();
            for (Image image : images) {
                ImagePojo imagePojo=new ImagePojo();
                imagePojo.setImageName(image.getName());
                imagePojo.setImageId(image.getId());
                imagePojo.setFlagNumber(0);
                imagePojo.setOpenstackIP(openstack.getOpenstackIP());
               imagesList.add(imagePojo);

            }

        return imagesList;
    }

    public static  List<? extends Image> createImage(OpenStack openstack) {
        return null;
    }
    public static String getFlag() {

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");  // 生成标准的 UUID 字符串
        String formattedUuid = uuid.substring(0, 6) + "-" +
                uuid.substring(6, 12) + "-" +
                uuid.substring(12, 18) + "-" +
                uuid.substring(18, 24);  // 截取 UUID 的部分字符

        return formattedUuid.toUpperCase();
    }


    public static void resetVmServer(VMservice vMservice,OpenStack openStack) {
        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openStack);
        String imageName = vMservice.getType();
        String serverIdToReset = vMservice.getVmID();
        // 获取虚拟实例服务
        ServerService serverService = osClient.compute().servers();

        // 获取要重置的虚拟实例
        Server serverToReset = serverService.get(serverIdToReset);
        List<? extends Image> list = osClient.compute().images().list();
        String imageId =null;
        if(imageName.contains("client")){
            imageName=imageName.substring(0,imageName.length()-7);
        }
        for (Image image: list ) {
            if(  image.getName().equals(imageName)){
                imageId=image.getId();
                    }
        }
        // 重置虚拟实例
        RebuildOptions rebuildOptions = RebuildOptions.create().image(imageId);
        // 重置虚拟实例
        ActionResponse response = serverService.rebuild(serverToReset.getId(), rebuildOptions);

        if (response.isSuccess()) {
            System.out.println("虚拟实例重置成功！");
        } else {
            System.out.println("虚拟实例重置失败。错误信息：" + response.getFault());
        }
    }

    //, OpenStack openstack, String vmName,, String networkName, String flavorName,List<String> flags
    public static RaceVm createClientVm(OpenStack openstack , String name,Integer num,String networkName, String flavorName ,String race) {
        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        String instanceName = race+"-"+name+"-"+num;
        Image image = null;

        for (Image a: osClient.compute().images().list()) {
            if(a.getName().equals(name)){
                image=a;
            }
        }
        // 获取网络
        Network network = osClient.networking().network().list().stream()
                .filter(n -> n.getName().equals(networkName))
                .findFirst()
                .orElse(null);

        // 获取硬件规格
        Flavor flavor = osClient.compute().flavors().list().stream()
                .filter(f -> f.getName().equalsIgnoreCase(flavorName))
                .findFirst()
                .orElse(null);

        List<String> ls=new ArrayList<>();
        ls.add(network.getId());


        Map<String, String> metadata = new HashMap<>();

        ServerCreateBuilder serverCreateBuilder = osClient.compute().servers().serverBuilder()
                .name(instanceName)
                .flavor(flavor)
                .image(image)
                .networks(ls)
                .keypairName("testkey").addMetadata(metadata);


        Server server = osClient.compute().servers().bootAndWaitActive(serverCreateBuilder.build(),6000000);
        ServerService serverService = osClient.compute().servers();

        RaceVm raceVm = new RaceVm(server.getId(),num,race,instanceName,new Date(),new Date(),"BUILDING");
        raceVm.setVmID(server.getId());
        raceVm.setStatus(String.valueOf(server.getStatus()));
        VNCConsole vncConsole = serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        serverService.getVNCConsole(server.getId(), VNCConsole.Type.NOVNC);
        String noVNCUrl = vncConsole.getURL();
        List<IpPort> ipPorts = ipPortMapper.getIpPorts();
        for (IpPort ipPort :ipPorts) {
            if(noVNCUrl.contains(ipPort.getPreIpport())){
                noVNCUrl=noVNCUrl.replace(ipPort.getPreIpport(),ipPort.getAftIpport());
            }
        }
        raceVm.setNoVNC(noVNCUrl);
        System.err.println(raceVm);
        return raceVm;
    }

    public static boolean deleteVm(OpenStack openstack ,String vmId) {
        OSClient.OSClientV3 osClient = CloudUtils.getOsclient(openstack);
        ActionResponse response = osClient.compute().servers().delete(vmId);
        if (response.isSuccess()) {
            System.out.println("实例删除成功");
        } else {
            System.out.println("实例删除失败：" + response.getFault());
        }
            return  response.isSuccess();
    }


}